<?php

    /**
     * Json
     *
     * @package      Core
     * @subpackage   Controller_Response
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    class Core_Controller_Response_Json extends Core_Controller_Response_Abstract
    {

	////////////////////////////////////////////////////////////////////////////
	//                                Variables                               //
	////////////////////////////////////////////////////////////////////////////

        /**
        * The response type
        *
        * @var string
        */
        protected $_type = 'json';

		/**
		 * Flag indicating wether the response can embed more than one error message
		 *
		 * @var boolean
		 */
        protected $_acceptSeveralErrors = false;

		/**
		 * PHP data to return
		 *
		 * @var mixed
		 */
		protected $_content = null;

		/**
		 * PHP data to return
		 *
		 * @var mixed
		 */
		protected $_exception = null;

		/**
		 * Number of results
		 *
		 * @var int|null
		 */
		protected $_count = null;

        /**
         * If the response contains meta information
         *
         * @var boolean
         */
        protected $_addMeta = true;

	////////////////////////////////////////////////////////////////////////////
	//                            Getters / Setters                           //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Sets the PHP data to return
         *
         * @param       mixed       $value
		 * @throws		Core_ArgumentNullException
         * @return      Core_Controller_Response_Json
         */
        public function setResponseContent($value)
        {
            if ($value === null) {
				throw new Core_ArgumentNullException('value is a null reference');
			}

            $this->_content = $value;
            return $this;
        }

        /**
         * Sets the PHP data to return
         *
         * @param       mixed       $value
		 * @throws		Core_ArgumentNullException
         * @return      Core_Controller_Response_Json
         */
        public function setResponseException($value)
        {
            if ($value === null) {
				throw new Core_ArgumentNullException('value is a null reference');
			}

            $this->_exception = $value;
            return $this;
        }

        /**
         * Sets the numbers of results to return
         *
         * @param       int|null        $value
         * @return      Core_Controller_Response_Json
         */
        public function setResponseCount($value)
        {
            if (!is_int($value) && !is_null($value)) {
				throw new Core_ArgumentException('value must be int or null');
			}

            $this->_count = $value;
            return $this;
        }
        
        /**
         * Sets if meta are added in the response
         *
         * @param       boolean     $value
         * @throws      Core_ArgumentException
         * @return      Core_Controller_Response_Json
         */
        public function setAddMeta($value)
        {
            if ($value === null) {
				throw new Core_ArgumentNullException('Fatal error : $value is a null reference');
			}

            if (!is_bool($value)) {
                throw new Core_ArgumentException('Fatal error : $value must be a boolean');
            }

            $this->_addMeta = $value;

            return $this;
        }

	////////////////////////////////////////////////////////////////////////////
	//                                 Methods                                //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Outputs the JSON content
         *
         * @throws      Core_Exception
         * @return      boolean     true if the generated content is ok
         */
        public final function output()
        {
			$this->_httpHeaders['Content-Type'] = "text/plain";

            $request = $this->_coordinator->getRequest();

            if (!($request instanceof Core_Controller_Request_Json)) {
                throw new Core_Exception('Fatal error: request isn\'t an instance of Core_Controller_Request_Json');
            }

            Core_Storage_Cookie::getInstance()->getMatchingCookies();

			if ($request->getJsonRequestId() !== null) {
                if ($this->_addMeta) {
                    $count  = (is_null($this->_count) ? count($this->_content) : $this->_count);
                    
                    $content = '{"result":'
                                . Zend_Json::encode($this->_content)
                                . ',"count": '. $count .',"error": null,"exception": '. Zend_Json::encode($this->_exception) .',"id":'
                                . Zend_Json::encode($this->_coordinator->getRequest()->getJsonRequestId())
                                . '}';
                } else {
                    $content = Zend_Json::encode($this->_content);
                }

				if ($this->hasErrors()) {
					return false;
				}

				$this->_httpHeaders['Content-length'] = strlen($content);
	            $this->sendHttpHeaders();
				echo $content;
			} else {
				if ($this->hasErrors()) {
					return false;
				}

				$this->_httpHeaders['Content-length'] = '0';
				$this->sendHttpHeaders();
			}

            return true;
        }

        /**
         * Outputs the errors
         *
         * @return      void
         */
        public final function outputErrors()
        {
			$errors = $this->_coordinator->getErrorMessages();

			if (count($errors)) {
				$e = $errors[0];
				$errorCode = $e[1];
				$errorMessage = '['. $e[0] .'] '. $e[2] .' (file: '. $e[3] .', line: '. $e[4] .')';
			} else {
				$errorMessage = 'Unknow error';
				$errorCode = -1;
			}

			$this->clearHttpHeaders();
			$this->_httpStatusCode = '500';
			$this->_httpStatusMsg = 'Internal Server Error';
			$this->_httpHeaders['Content-Type'] = "text/plain";

			$content = '{"result":null,"error":{"code": '
						. Zend_Json::encode($errorCode)
						. ', "string":'
						. Zend_Json::encode($errorMessage)
						. ' },"id":'
						. Zend_Json::encode($coordinator->getRequest()->getJsonRequestId())
						. '}';

			$this->_httpHeaders['Content-length'] = strlen($content);
			$this->sendHttpHeaders();

			echo $content;
        }
    }
